import * as app from '../../common/utils/BaseApp'
import { deepClone, getDictName } from '@/utils'
import * as ck from '../../common/utils/validater'
import * as utils from '@/utils/verify'
import { hasActionPriv } from '@/utils/perm'
import * as elg from '../../common/utils/ElmGenerator'
import { flatArrayToTree } from '../../common/utils/ComUtil'
import store from '@/store'

import { getMenuAllList, getMenuTreeList, createMenu, updateMenu, deleteMenu } from '@/api/system/menu'
import langFile from './menu.lang'
const base = app.install({ langObj: langFile })
const pageMode = {
  add: 'add',
  detailAdd: 'detailAdd',
  update: 'update'
}
const menuType = {
  module: '1', // 模块
  menu: '2', // 菜单
  feature: '3' // 功能
}
export default {
  mixins: [base],
  data() {
    return {
      formObj: {
        searchForm: {
          // ----------------------- 菜单查询条件 ---------------------
          menu: {
            menuName: '',
            status: ''
          },
          likeSearch: {
            menu: ['menuName']
          }
        },
        addForm: {
          // ----------------------- 菜单Form结构 ---------------------
          menu: {
            id: undefined,	// ID
            menuId: '',	// 权限ID
            menuParent: '',	// 权限父节点
            menuType: menuType.module,	// 权限类型（模块，菜单，按钮）
            routeName: '',	// 模块名，路由名，按钮名
            displayNameZh: '',	// 路由显示名(中)
            displayNameJa: '',	// 路由显示名(日)
            displayNameEn: '',	// 路由显示名(英)
            routePath: '',	// 路由Path
            routeView: '',	// 路由View控件
            iconName: '',	// Icon
            sortOrder: '',	// 排序
            webPerms: '',	// 前端权限
            apiPerms: '',	// Api权限
            hiddenFlg: '0',	// 是否显示在侧边栏(hidden_in_sidebar)
            nocacheFlg: '0',	// 是否不缓存：noCache
            status: '1',	// 禁用/起用（0-禁用,1-起用）
            memo: '',	// Memo

            redirectPath: 'noRedirect',	// 在面包屑导航中是否可被点击(breadcrumb_nav)：redirect
            alwaysShowFlg: '1',	// 一直显示根路由：alwaysShow
            breadcrumbFlg: '1',	// 是否在面包屑中显示
            fixTagFlg: '0',	// 是否固定在tags-view中
            activeMenu: ''	// 高亮侧边栏(比如：/article/list)
          },
          showFlg: {
            menu: false
          },
          showMode: {
            menu: ''
          },
          menuTreeList: [],
          menuTreeData: []
        }
      },
      listObj: {
        // ----------------------- 菜单列表 ---------------------
        menu: {
          ...base.$gcom.getDefListObj()
        }
      }
    }
  },
  computed: {
    isAddMenu() {
      return this.formObj.addForm.showMode.menu === pageMode.add ||
              this.formObj.addForm.showMode.menu === pageMode.detailAdd
    },
    menuSearchFormLayout() {
      const formItems = [
        elg.createInput(this, { bindId: 'menuName', propsOpt: { width: 180 }}),
        elg.createSelect(this, { bindId: 'status',
          optionList: elg.createChildOption(this.$dictObj['sys_activate_flg'].dict), propsOpt: { width: 160 }}),
        hasActionPriv(['sys:menu:query']) === false ? null
          : elg.createButton(this, this.handleSearchMenu, { langId: 'search', actionValid: true, propsOpt: { icon: 'el-icon-search' }}),
        elg.createBR(),
        hasActionPriv(['sys:menu:add']) === false ? null
          : elg.createButton(this, this.handleAddMenu, { langId: 'add', propsOpt: { icon: 'el-icon-edit' }})
      ]
      const rules = {
        routeName: [ck.createMaxLenValidater(this, 30)]
      }
      return { formItems: formItems, rules: rules }
    },
    routeNameLang() {
      if (this.formObj.addForm.menu.menuType === menuType.module) return 'routeNameM'
      if (this.formObj.addForm.menu.menuType === menuType.menu) return 'routeNameR'
      if (this.formObj.addForm.menu.menuType === menuType.feature) return 'routeNameF'
    },
    menuParentLang() {
      if (this.formObj.addForm.menu.menuType === menuType.module) return 'menuParent'
      if (this.formObj.addForm.menu.menuType === menuType.menu) return 'menuParentModule'
      if (this.formObj.addForm.menu.menuType === menuType.feature) return 'menuParentMenu'
    },
    menuAddFormLayout() {
      // 1: 模块，2：菜单，3: 功能
      const menuParentHidden = (this.formObj.addForm.menu.menuType === menuType.module)
      const displayNameHidden = (this.formObj.addForm.menu.menuType === menuType.feature)
      const routeViewHidden = (this.formObj.addForm.menu.menuType === menuType.module || this.formObj.addForm.menu.menuType === menuType.feature)
      const permsHidden = (this.formObj.addForm.menu.menuType === menuType.module || this.formObj.addForm.menu.menuType === menuType.menu)
      const iconNameHidden = (this.formObj.addForm.menu.menuType === menuType.feature)
      const nocacheFlgHidden = (this.formObj.addForm.menu.menuType === menuType.module || this.formObj.addForm.menu.menuType === menuType.feature)
      const hiddenFlgHidden = (this.formObj.addForm.menu.menuType === menuType.feature)
      const hiddenDefault = true

      if (this.formObj.addForm.menu.menuType === menuType.menu) {
        this.formObj.addForm.menuTreeData = flatArrayToTree(this.formObj.addForm.menuTreeList.filter(item => {
          return item.menuType === menuType.module
        }), {})
      }
      if (this.formObj.addForm.menu.menuType === menuType.feature) {
        this.formObj.addForm.menuTreeData = flatArrayToTree(this.formObj.addForm.menuTreeList, {})
      }

      let menuParentDisabled = false
      let sysMenuType = deepClone(this.$dictObj['sys_menu_type'].dict)
      // eslint-disable-next-line no-empty
      if (this.formObj.addForm.showMode.menu === pageMode.add) {
      } else if (this.formObj.addForm.showMode.menu === pageMode.detailAdd) {
        sysMenuType = sysMenuType.map((item) => {
          item['disabled'] = this.formObj.addForm.menu.menuType !== item.id
          return item
        })
        menuParentDisabled = true
      } else if (this.formObj.addForm.showMode.menu === pageMode.update) {
        sysMenuType = sysMenuType.map((item) => {
          item['disabled'] = this.formObj.addForm.menu.menuType !== item.id
          return item
        })
      }
      const formItems = [
        // 权限类型（模块，菜单，按钮）
        elg.createRadioButtonGroup(this, { bindId: 'menuType',
          optionList: elg.createChildRadioButton(sysMenuType) }),
        // 权限父节点(2：菜单，3: 功能)
        menuParentHidden ? null : elg.createSelectTree(this, { bindId: 'menuParent', langId: this.menuParentLang, isDisabled: menuParentDisabled,
          treeData: this.formObj.addForm.menuTreeData, propsOpt: { visiable: false, multiple: false, onlyLastNodes: true }}),
        // 路由显示名(中) (1: 模块，2：菜单)
        displayNameHidden ? null : elg.createInput(this, { bindId: 'displayNameZh' }),
        // 路由显示名(日) (1: 模块，2：菜单)
        displayNameHidden ? null : elg.createInput(this, { bindId: 'displayNameJa' }),
        // 路由显示名(英) (1: 模块，2：菜单)
        displayNameHidden ? null : elg.createInput(this, { bindId: 'displayNameEn' }),
        // 模块名，路由名，按钮名 = // 路由Path
        elg.createInput(this, { bindId: 'routeName', langId: this.routeNameLang }),
        // 路由View控件 (2：菜单)
        routeViewHidden ? null : elg.createInput(this, { bindId: 'routeView' }),
        // Icon (1: 模块，2：菜单)
        iconNameHidden ? null : elg.createSelectIcon(this, { bindId: 'iconName' }),

        // 前端权限 (3:功能)
        permsHidden ? null : elg.createInput(this, { bindId: 'webPerms' }),
        // Api权限 (3:功能)
        permsHidden ? null : elg.createInput(this, { bindId: 'apiPerms' }),
        // 排序
        elg.createInputNumber(this, { bindId: 'sortOrder' }),

        // 是否显示在侧边栏(hidden_in_sidebar)
        hiddenFlgHidden ? null : elg.createRadioGroup(this, { bindId: 'hiddenFlg',
          optionList: elg.createChildRadio(this.$dictObj['sys_hidden_flg'].dict) }),
        // 是否不缓存：noCache
        nocacheFlgHidden ? null : elg.createRadioGroup(this, { bindId: 'nocacheFlg',
          optionList: elg.createChildRadio(this.$dictObj['sys_nocache_flg'].dict) }),
        // 禁用/可用（0-禁用,1-可用）
        elg.createRadioGroup(this, { bindId: 'status',
          optionList: elg.createChildRadio(this.$dictObj['sys_activate_flg'].dict) }),

        // Memo
        elg.createTextArea(this, { bindId: 'memo' }),

        // 在面包屑导航中是否可被点击(breadcrumb_nav)：redirect （1: 模块）
        hiddenDefault ? null : elg.createInput(this, { bindId: 'redirectPath' }),
        // 一直显示根路由：alwaysShow （1: 模块）
        hiddenDefault ? null : elg.createRadioGroup(this, { bindId: 'alwaysShowFlg',
          optionList: elg.createChildRadio(this.$dictObj['sys_always_show_flg'].dict) }),
        // 是否在面包屑中显示
        hiddenDefault ? null : elg.createRadioGroup(this, { bindId: 'breadcrumbFlg',
          optionList: elg.createChildRadio(this.$dictObj['sys_breadcrumb_show_flg'].dict) }),
        // 是否固定在tags-view中
        hiddenDefault ? null : elg.createRadioGroup(this, { bindId: 'fixTagFlg',
          optionList: elg.createChildRadio(this.$dictObj['sys_fix_tag_flg'].dict) }),
        // 高亮侧边栏(比如：/article/list)
        hiddenDefault ? null : elg.createInput(this, { bindId: 'activeMenu' })
      ]
      const footerItems = [
        hasActionPriv(['sys:menu:add', 'sys:menu:update']) === false ? null
          : elg.createButton(this, this.handleSaveMenu, { langId: 'confirm', actionValid: true, propsOpt: { icon: '' }})
      ]

      const rules = {
        menuType: [
          ck.createRequiredValidater(this)
        ],
        menuParent: [
          ck.createRequiredValidater(this), ck.createCustomValidater(this, this.parentMenuNotExistValidator)
        ],
        displayNameZh: [
          ck.createRequiredValidater(this), ck.createMaxLenValidater(this, 30)
        ],
        displayNameJa: [
          ck.createMaxLenValidater(this, 30)
        ],
        displayNameEn: [
          ck.createMaxLenValidater(this, 30)
        ],
        routeName: [
          ck.createRequiredValidater(this), ck.createMaxLenValidater(this, 30)
        ],
        routeView: [
          ck.createRequiredValidater(this), ck.createMaxLenValidater(this, 150)
        ],
        webPerms: [
          ck.createMaxLenValidater(this, 30)
        ],
        apiPerms: [
          ck.createMaxLenValidater(this, 30)
        ],
        sortOrder: [
          ck.createRequiredValidater(this)
        ],
        memo: [
          ck.createMaxLenValidater(this, 255)
        ]
      }
      return { formItems: formItems, footerItems: footerItems, rules: rules }
    },
    menuListLayout() {
      const sysActivateFlg = this.$dictObj['sys_activate_flg'].dict.map((item) => {
        const color = item.id === '0' ? '#ed1941' : '#1890ff'
        return { ...item, color: color }
      })

      const itemColumns = [
        elg.createTableColumn(this, { bindId: 'detailName', langId: 'detailName', align: 'left' }),
        elg.createTableColumn(this, { bindId: 'sortOrder', align: 'center', width: '50' }),
        elg.createTableColumn(this, { bindId: 'menuType',
          formatter: {
            formatFnc: (row, v) => {
              return getDictName(this.$dictObj['sys_menu_type'].dict, v)
            }
          },
          align: 'center' }),
        elg.createTableColumn(this, { bindId: elg.createSvgIcon(this, { bindId: 'iconName' }), align: 'center', width: '50' }),
        elg.createTableColumn(this, { bindId: 'routeView', align: 'left' }),
        elg.createTableColumn(this, { bindId: 'webPerms', align: 'left' }),
        elg.createTableColumn(this, { bindId: 'apiPerms', align: 'left' }),
        elg.createTableColumn(this, { bindId: elg.createTag(this, { bindId: 'status', optionList: sysActivateFlg }), align: 'center', width: 40 }),
        elg.createTableColumn(this, { bindId: 'memo', align: 'center' })

      ]
      const actionColumns = [
        hasActionPriv(['sys:menu:add']) === false ? null
          : elg.createTableAction(this, { langId: 'add', actionFnc: this.handleDetailAddMenu, visableFnc: (row, index) => {
            return (row.menuType !== '3')
          } }),
        hasActionPriv(['sys:menu:update']) === false ? null
          : elg.createTableAction(this, { langId: 'edit', actionFnc: this.handleUpdateMenu }),
        hasActionPriv(['sys:menu:delete']) === false ? null
          : elg.createTableAction(this, { langId: 'delete', actionFnc: this.handleDeleteMenu, visableFnc: (row, index) => {
            return (row.canDelete === '1')
          } })
      ]
      return { columns: itemColumns, actions: actionColumns }
    }
  },
  created() {
    this.$gcom.formObj = deepClone(this.formObj)
    this.searchMenuList()
  },
  methods: {
    handleSearchMenu() {
      this.validateAll(['searchForm'], () => {
        this.listObj.menu.pagingDefine.page = 1
        this.searchMenuList()
      })
    },
    handleAddMenu(row, index) {
      this.handleOpenMenuDialog(pageMode.add, row, index)
    },
    handleDetailAddMenu(row, index) {
      this.handleOpenMenuDialog(pageMode.detailAdd, row, index)
    },
    handleUpdateMenu(row, index) {
      this.handleOpenMenuDialog(pageMode.update, row, index)
    },
    async handleOpenMenuDialog(mode, row, index) {
      this.formObj.addForm.showMode.menu = mode
      await this.searchMenuTreeList()
      this.formObj.addForm.menuTreeList = this.formObj.addForm.menuTreeList.map((item) => {
        return { id: item.menuId, name: item[this.getLangField()], parentId: item.menuParent, menuType: item.menuType }
      })
      this.formObj.addForm.menuTreeData = flatArrayToTree(this.formObj.addForm.menuTreeList, {})
      this.openDialog('menu', mode, row)
    },
    getLangField() {
      let menuNameField = 'displayNameZh'
      if (store.getters.language === 'ja') {
        menuNameField = 'displayNameJa'
      } else if (store.getters.language === 'en') {
        menuNameField = 'displayNameEn'
      }
      return menuNameField
    },
    handleSaveMenu() {
      this.validateAll(['menuEditDlg'], async() => {
        if (this.isAddMenu) {
          const _form = { ...this.$gcom.formObj.addForm.menu } // 默认值
          const _change = { ... this.formObj.addForm.menu } // 输入值
          if (_change.menuType === menuType.module) {
            const keyObj = {
              menuType: '',	// 权限类型（模块，菜单，按钮）
              displayNameZh: '',	// 路由显示名(中)
              displayNameJa: '',	// 路由显示名(日)
              displayNameEn: '',	// 路由显示名(英)
              routeName: '',	// 模块名，路由名，按钮名
              iconName: '',	// Icon
              sortOrder: '',	// 排序
              hiddenFlg: '',	// 是否显示在侧边栏(hidden_in_sidebar)
              status: '',	// 禁用/起用（0-禁用,1-起用）
              memo: ''	// Memo
            }
            Object.keys(keyObj).forEach((key) => {
              _form[key] = _change[key]
            })
            _form.routePath = '/' + _form.routeName
          } else if (_change.menuType === menuType.menu) {
            const keyObj = {
              menuType: '',	// 权限类型（模块，菜单，按钮）
              menuParent: '',	// 权限父节点
              displayNameZh: '',	// 路由显示名(中)
              displayNameJa: '',	// 路由显示名(日)
              displayNameEn: '',	// 路由显示名(英)
              routeName: '',	// 模块名，路由名，按钮名
              routeView: '',	// 路由View控件
              iconName: '',	// Icon
              sortOrder: '',	// 排序
              hiddenFlg: '',	// 是否显示在侧边栏(hidden_in_sidebar)
              nocacheFlg: '',	// 是否不缓存：noCache
              status: '',	// 禁用/起用（0-禁用,1-起用）
              memo: ''	// Memo
            }
            Object.keys(keyObj).forEach((key) => {
              _form[key] = _change[key]
            })
            _form.routePath = _form.routeName
          } else if (_change.menuType === menuType.feature) {
            const keyObj = {
              menuType: '',	// 权限类型（模块，菜单，按钮）
              menuParent: '',	// 权限父节点
              routeName: '',	// 模块名，路由名，按钮名
              webPerms: '',	// 前端权限
              apiPerms: '',	// Api权限
              sortOrder: '',	// 排序
              status: '',	// 禁用/起用（0-禁用,1-起用）
              memo: ''	// Memo
            }
            Object.keys(keyObj).forEach((key) => {
              _form[key] = _change[key]
            })
            _form.displayNameZh = _form.routeName
          }
          await createMenu(_form)
        } else {
          const _form = { ... this.formObj.addForm.menu } // 输入值
          await updateMenu(_form)
        }
        this.searchMenuList()
        this.formObj.addForm.showFlg.menu = false
      })
    },
    async handleDeleteMenu(row, index) {
      let msg = null
      if (row.menuType === menuType.module) {
        msg = 'message.rule.delModulConfirm'
      }
      if (row.menuType === menuType.menu) {
        msg = 'message.rule.delMenuConfirm'
      }
      if (row.menuType === menuType.feature) {
        msg = 'message.rule.delFncConfirm'
      }
      this.$showConfirm({ msg: this.getLang(msg), ok: async() => {
        await deleteMenu(row.id)
        setTimeout(async() => {
          await this.searchMenuList()
        }, 500)
      } })
    },
    // ----------------------- 菜单列表查询 ---------------------
    async searchMenuTreeList() {
      const result = await getMenuTreeList()
      this.formObj.addForm.menuTreeList = result.data.listLine
    },
    async searchMenuList() {
      const _target = this.listObj.menu
      try {
        _target.listLineLoading = true
        const result = await getMenuAllList({
          searchForm: this.formObj.searchForm.menu,
          likeSearch: this.formObj.searchForm.likeSearch.menu,
          pagingDefine: this.listObj.menu.pagingDefine
        })

        _target.listLine = result.data.listLine.map((item) => {
          const langVal = utils.isNotContainsVal(item[this.getLangField()]) ? item.displayNameZh : item[this.getLangField()]
          return { treeId: item.menuId, detailName: langVal, ...item }
        })
        _target.listLine = flatArrayToTree(_target.listLine, { schema: { id: 'menuId', name: 'routeName', parentId: 'menuParent' }})
        _target.lineNum = result.data.lineNum
      } catch (err) {
        console.log(err)
      } finally {
        setTimeout(() => {
          _target.listLineLoading = false
        }, 0)
      }
    },

    // ----------------------- Open Dialog ---------------------
    openDialog(target, mode, row, index) {
      const data = mode === pageMode.update ? row : this.$gcom.formObj.addForm[target]
      this.formObj.addForm[target] = { ...data }
      if (mode === pageMode.detailAdd) {
        // 明细行的[新增]的时候，所属上级=自己，菜单类型=自己的下一级
        this.formObj.addForm[target].menuParent = row.menuId
        this.formObj.addForm[target].menuType = String(Number(row.menuType) + 1)
      }
      this.formObj.addForm.showFlg[target] = true
    },
    // ----------------------- 所属模块/所属菜单 是否存在 ---------------------
    parentMenuNotExistValidator(rule, value, callback) {
      if (this.formObj.addForm.menuTreeList.length > 0) {
        const exist = this.formObj.addForm.menuTreeList.some(item => {
          return this.formObj.addForm.menu.menuType === menuType.module ||
          (item.menuType === menuType.module && value === item.id && this.formObj.addForm.menu.menuType === menuType.menu) ||
          (item.menuType === menuType.menu && value === item.id && this.formObj.addForm.menu.menuType === menuType.feature)
        })
        if (!exist) {
          callback(new Error((this.formObj.addForm.menu.menuType === menuType.menu)
            ? this.getLang('message.rule.menuParentNotExist01') : this.getLang('message.rule.menuParentNotExist02')))
        } else {
          callback()
        }
      } else {
        callback()
      }
    }
  }
}
